#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "gps_usart.h"

#include <string.h>
#include "voice.h"


static const char* TAG = "GPS任务";

//任务列表
void gps_uart_receive_task(void *param);        // GPS_UART 接收任务
void timer_task(void* arg);

#include "rs485.h"
static void rs485_tx_task(void *arg);
static void rs485_rx_task(void *arg);

#include "lcd.h"

void app_main(void) {

    //NVS初始化
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
     ESP_LOGI("485测试","测试11测试");
    //spi2_init(); 
    //lcd_init();  
    //lcd_show_string(20, 0, 200, 16, 16, "ESP32-S3-2",BLACK);
    
    //GPS模块初始化
   // gps_usart_init(9600);

    //voice_init_uart();
    rs485_init();
    //RTOS任务创建列表----数字越大代表优先级越高
    //GPS收发任务
    //xTaskCreatePinnedToCore(timer_task, "timer_task", 4096, NULL, 5, NULL, 1);
    
    //rs485任务
    xTaskCreatePinnedToCore(rs485_tx_task, "rs485_tx_task", 2048, NULL, 5, NULL, 0);
    xTaskCreatePinnedToCore(rs485_rx_task, "rs485_rx_task", 2048, NULL, 5, NULL, 0);

    // gps任务
   // xTaskCreatePinnedToCore(gps_uart_receive_task, "gps_uart_receive_task", 4096, NULL, 5, NULL, 1);
}

// 发送任务
static void rs485_tx_task(void *arg) {

    while (1) 
    {   
        rs485_send_string("485通信测试");
        ESP_LOGI("CES","455ING");
        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

// 接收任务
static void rs485_rx_task(void *arg) {
    uint8_t buffer[RS485_BUF_SIZE];
    while (1) {
        int length = uart_read_bytes(RS485_UART_PORT, buffer, sizeof(buffer), pdMS_TO_TICKS(100));
        if (length > 0) {
            buffer[length] = '\0'; // 确保字符串结尾
            ESP_LOGI(TAG, "Received: \"%s\" (%d bytes)", buffer, length);
        }
    }
}






// 校验和验证函数
bool validate_checksum1(const char *sentence) {
    int len = strlen(sentence);
    if (len < 5) return false; // 最小长度检查
    char *end = strchr(sentence, '*');
    if (end == NULL) return false; // 检查校验和分隔符
    int checksum = 0;
    for (int i = 1; i < end - sentence; i++) {
        checksum ^= sentence[i];
    }
    int provided_checksum = strtol(end + 1, NULL, 16);
    return checksum == provided_checksum;
}

// 解析 NMEA 句子并存储到 JSON
void parse_nmea_to_json(const char *sentence, cJSON *json) {
    if (sentence == NULL || json == NULL) {
        ESP_LOGE(TAG, "Invalid input parameters");
        return;
    }

    char *sentence_copy = strdup(sentence);
    if (sentence_copy == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for sentence copy");
        return;
    }

    char *sentence_type = strtok(sentence_copy, ",");
    if (sentence_type == NULL) {
        free(sentence_copy);
        return;
    }

    cJSON *sentence_obj = cJSON_CreateObject();
    if (sentence_obj == NULL) {
        free(sentence_copy);
        return;
    }
    cJSON_AddItemToObject(json, sentence_type, sentence_obj);

    // 根据句子类型解析字段
    if (strcmp(sentence_type, "$GNGGA") == 0) {
        // $GNGGA - Global Positioning System Fix Data
        char *fields[15];
        int field_count = 0;
        char *token = strtok(NULL, ",");
        while (token != NULL && field_count < 15) {
            fields[field_count++] = token;
            token = strtok(NULL, ",");
        }
         // 打印解析后的字段
        ESP_LOGI(TAG, "Parsed $GNGGA fields:");
        for (int i = 0; i < field_count; i++) {
            ESP_LOGI(TAG, "Field %d: %s", i + 1, fields[i] ? fields[i] : "(empty)");
        }
        // 检查定位质量字段是否为有效状态
        if (fields[1] && strcmp(fields[1], "0") != 0) {
            // 添加字段到 JSON 对象
            cJSON_AddStringToObject(sentence_obj, "UTC_Time", fields[0] ? fields[0] : "");                      // UTC时间
            cJSON_AddStringToObject(sentence_obj, "Latitude", fields[1] ? fields[1] : "");                      // 纬度
            cJSON_AddStringToObject(sentence_obj, "Latitude_Direction", fields[2] ? fields[2] : "");            // 纬度半球
            cJSON_AddStringToObject(sentence_obj, "Longitude", fields[3] ? fields[3] : "");                     // 经度
            cJSON_AddStringToObject(sentence_obj, "Longitude_Direction", fields[4] ? fields[4] : "");           // 经度半球
            cJSON_AddStringToObject(sentence_obj, "Fix_Quality", fields[5] ? fields[5] : "");                   // 定位质量指示，0=定位无效，1=定位有效
            cJSON_AddStringToObject(sentence_obj, "Satellites_Used", fields[6] ? fields[6] : "");               // 使用卫星数量
            cJSON_AddStringToObject(sentence_obj, "HDOP", fields[7] ? fields[7] : "");                          // 水平精度因子(HDOP)
            cJSON_AddStringToObject(sentence_obj, "Altitude", fields[8] ? fields[8] : "");                      // 海拔高度
            cJSON_AddStringToObject(sentence_obj, "Altitude_Unit", fields[9] ? fields[9] : "");                 // 海拔高度单位
            cJSON_AddStringToObject(sentence_obj, "Geoidal_Separation", fields[10] ? fields[10] : "");          // 大地水准面高度
            cJSON_AddStringToObject(sentence_obj, "Geoidal_Separation_Unit", fields[11] ? fields[11] : "");     // 大地水准面高度单位
        } else {
            ESP_LOGW(TAG, "Invalid GPS fix. Skipping GPS process.");
        }
    } else if (strcmp(sentence_type, "$GPTXT") == 0) {
        // $GPTXT - Text Message
        char *fields[5];
        int field_count = 0;
        char *token = strtok(NULL, ",");
        while (token != NULL && field_count < 5) {
            fields[field_count++] = token;
            token = strtok(NULL, ",");
        }
        // 添加字段到 JSON 对象
        cJSON_AddStringToObject(sentence_obj, "Message_Number", fields[0] ? fields[0] : "");                // 消息编号
        cJSON_AddStringToObject(sentence_obj, "Total_Messages", fields[1] ? fields[1] : "");                // 总消息数
        cJSON_AddStringToObject(sentence_obj, "Message_Sequence", fields[2] ? fields[2] : "");              // 消息顺序
        cJSON_AddStringToObject(sentence_obj, "Message_Text", fields[3] ? fields[3] : "");                  // 文本内容
    } else {
        // 其他句子类型，使用通用字段名称
        int field_num = 1;
        char *token = strtok(NULL, ",");
        while (token != NULL) {
            char field_name[16];
            snprintf(field_name, sizeof(field_name), "Field%d", field_num++);
            cJSON_AddStringToObject(sentence_obj, field_name, token);
            token = strtok(NULL, ",");
        }
    }

    free(sentence_copy);
}

void gps_uart_receive_task(void *param) {
    ESP_LOGI(TAG, "任务已创建!");
    uint8_t *uart_rx_buffer = (uint8_t *)malloc(GPS_RX_BUF_SIZE); // 分配接收缓冲区
    if (uart_rx_buffer == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for UART receive buffer");
        vTaskDelete(NULL); // 如果分配失败，删除任务
        return;
    }

    //cJSON *root_json = cJSON_CreateArray(); // 创建 JSON 数组
    //cJSON *current_json = NULL; // 当前 JSON 对象，初始为空

    while (1) {
        int length = uart_read_bytes(GPS_USART_UX, uart_rx_buffer, GPS_RX_BUF_SIZE, pdMS_TO_TICKS(100)); // 读取 UART 数据
        if (length > 0) {
            for (int i = 0; i < length; i++) {
                if (uart_rx_buffer[i] == '$') {
                    int end = -1;
                    for (int j = i + 1; j < length; j++) {
                        if (uart_rx_buffer[j] == '\r' && uart_rx_buffer[j + 1] == '\n') {
                            end = j + 1;
                            break;
                        }
                    }
                    if (end != -1) {
                        char sentence[end - i + 1];
                        memcpy(sentence, &uart_rx_buffer[i], end - i);
                        sentence[end - i] = '\0';

                        if (validate_checksum1(sentence)) {


                            //方便其他调试，先注释此处。
                           // ESP_LOGI(TAG, "Received valid sentence: %s", sentence);



                            /*
                            if (strncmp(sentence, "$GNGGA", 6) == 0) {
                                // 遇到 $GNGGA，开始一个新的 JSON 对象
                                if (current_json != NULL) {
                                    // 如果当前 JSON 对象不为空，先将其添加到数组中
                                    cJSON_AddItemToArray(root_json, current_json);
                                }
                                current_json = cJSON_CreateObject(); // 创建新的 JSON 对象
                                if (current_json != NULL) {
                                    parse_nmea_to_json(sentence, current_json); // 解析 $GNGGA 内容并添加到 JSON
                                }
                            } else if (strncmp(sentence, "$GPTXT", 6) == 0) {
                                // 遇到 $GPTXT，解析内容并结束当前 JSON 对象
                                if (current_json != NULL) {
                                    parse_nmea_to_json(sentence, current_json); // 解析 $GPTXT 内容并添加到 JSON
                                    cJSON_AddItemToArray(root_json, current_json); // 将当前 JSON 对象添加到数组中
                                    // 打印 JSON 数据
                                    char *json_str = cJSON_Print(root_json);
                                    if (json_str != NULL) {
                                        ESP_LOGI(TAG, "JSON Data:\n%s", json_str);
                                        free(json_str);
                                    }
                                    // 清空 JSON 数组
                                    cJSON_Delete(root_json);
                                    root_json = cJSON_CreateArray();
                                    current_json = NULL; // 清空当前 JSON 对象
                                }
                            } else {
                                // 其他句子，添加到当前 JSON 对象中
                                if (current_json != NULL) {
                                    parse_nmea_to_json(sentence, current_json);
                                }
                            }
                            */
                            
                            
                        } else {
                            ESP_LOGW(TAG, "Received invalid sentence: %s", sentence);
                        }

                        memmove(uart_rx_buffer, &uart_rx_buffer[end + 1], length - end - 1);
                        length -= (end + 1);
                        i = -1; // 重新搜索帧头
                    }
                }
            }
        }
    }

    free(uart_rx_buffer);
    //cJSON_Delete(root_json);
    vTaskDelete(NULL);
}

// 定时器任务
void timer_task(void* arg)
{   
    uint8_t data;

    vTaskDelay(pdMS_TO_TICKS(400));

    data = 0x0A;
    send_data(&data, sizeof(data));
    vTaskDelay(pdMS_TO_TICKS(400));

    data = 0x03;
    send_data(&data, sizeof(data));
    vTaskDelay(pdMS_TO_TICKS(400));

    data = 0x00;
    send_data(&data, sizeof(data));
    vTaskDelay(pdMS_TO_TICKS(400));

    data = 0x0C;
    send_data(&data, sizeof(data));
    vTaskDelay(pdMS_TO_TICKS(400));

    send_data((const uint8_t*)"/启动*/启动语言*???", sizeof("/启动*/启动语言*???"));


    ESP_LOGI("INIT","RS_485初始化完成！");
    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(5000)); // 每2秒发送一次命令
        ESP_LOGI("MP3","下一首");
        send_data(NextFile, get_NextFile_size()); // 发送下一个文件命令
    }
}